﻿using System;
using Microsoft.Office.Interop.Word;

namespace XD.Office
{
    /// <summary>
    /// Work文档模版导出
    /// </summary>
    public partial class DocTemplateExporter
    {
        //模版对象
        private TemplateParams _param = null;
        //Office Word APP 对象
        private Application _app = null;
        //文档
        private Document _doc = null;
        //输出文件
        private string _docFile = "";
        //是否已复制模版文件到目标路径
        private bool _hasCopied = false;

        /// <summary>
        /// 不使用模版默认导出
        /// </summary>
        /// <param name="docFile">输出文件</param>
        public DocTemplateExporter(string docFile)
        {
            _param = new TemplateParams();
            _docFile = docFile;
        }

        /// <summary>
        /// 指定模版导出
        /// </summary>
        /// <param name="param"></param>
        /// <param name="docFile">输出文件</param>
        public DocTemplateExporter(TemplateParams param, string docFile)
        {
            _param = param;
            _docFile = docFile;
            if (_param == null)
            {
                _param = new TemplateParams();
            }
        }
        ~DocTemplateExporter()
        {
            Close();
        }

        /// <summary>
        /// 进度控件
        /// </summary>
        public System.Windows.Forms.ProgressBar ProgressBar { get; set; }

        /// <summary>
        /// 获取、设置 模版参数对象
        /// set：如果已经打开输出流，则不会重新复制、打开模版文件
        /// </summary>
        public TemplateParams Template
        {
            get
            {
                return _param;
            }
            set
            {
                _param = value;
            }
        }
        /// <summary>
        /// 保存
        /// </summary>
        public void Save()
        {
            object missing = Type.Missing;
            object savefile = _docFile;
            if (_hasCopied)
            {
                _doc.Save();
            }
            else
            {
                _doc.SaveAs(ref savefile, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing
                    , ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                _hasCopied = true;
            }
        }

        /// <summary>
        /// 关闭(重要）
        /// </summary>
        public void Close()
        {
            object missing = Type.Missing;
            object savechange = false;
            if (_doc != null)
            {
                _doc.Close(ref savechange, ref missing, ref missing);
            }
            if (_app != null)
            {
                _app.Quit(ref savechange, ref missing, ref missing);
            }
            _app = null;
            _doc = null;
        }

        /// <summary>
        /// 导出数据卡
        /// </summary>
        /// <param name="row">数据行</param>
        /// <param name="docFile">输出文件</param>
        /// <returns></returns>
        public bool ExportDataCar(System.Data.DataRow row)
        {
            bool ok = false;

            object missing = Type.Missing;
            try
            {
                OpenDocument();

                string[] columns = GetColumns(row.Table);
                //替换
                object replaceOption = WdReplace.wdReplaceAll;
                System.Data.DataTable table = row.Table;
                for (int i = 0; i < columns.Length;i++)
                {
                    object v = row[columns[i]];
                    object value = "";
                    if (v != DBNull.Value)
                    {
                        value = Convert.ToString(v);
                    }
                    object oldStr = string.Format(_param.ReplaceRule, table.Columns[i].ColumnName.ToUpper());
                    object matchCase = (object)false;
                    _doc.Content.Find.ClearFormatting();
                    if (table.Columns[i].Caption.Equals(Constant.PhotoTag))
                    {
                        //查找字符串替换成指定的图片
                        string fileName = (string)value;
                        if (System.IO.File.Exists(fileName))
                        {
                            _doc.Application.Selection.Find.ClearFormatting();
                            _doc.Application.Selection.Find.Text = (string)oldStr;
                            while (_doc.Application.Selection.Find.Execute(ref missing, ref matchCase, ref missing, ref missing, ref missing, ref missing,
                                ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing))
                            {
                                Range range = _doc.Application.Selection.Next();
                                if (range != null)
                                {
                                    //删除文本
                                    this.DeleteChar(((string)oldStr).Length - 2);
                                    //插入图片
                                    range.InlineShapes.AddPicture(fileName, ref missing, ref missing, ref missing);
                                }
                            }
                        }
                        else
                        {
                            value = (object)(String.Empty);
                            _doc.Content.Find.Execute(ref oldStr, ref matchCase, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                                ref value, ref replaceOption, ref missing, ref missing, ref missing, ref missing);
                        }
                    }
                    else
                    {
                        //查找字符串并替换                      
                        _doc.Content.Find.Execute(ref oldStr, ref matchCase, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                            ref value, ref replaceOption, ref missing, ref missing, ref missing, ref missing);
                    }
                }
                ok = true;

            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }

            return ok;
        }

        /// <summary>
        /// 导出数据表
        /// </summary>
        /// <param name="table"></param>
        /// <param name="docFile"></param>
        /// <returns></returns>
        public bool ExportData(System.Data.DataTable table)
        {
            bool ok = false;

            object missing = Type.Missing;
            try
            {
                OpenDocument();

                //获取列名称
                string[] columns = GetColumns(table);
                //获取表格
                Table dataRange = GetDocTable(_doc, _app, columns);

                if (ProgressBar != null)
                {
                    ProgressBar.Value = 0;
                    ProgressBar.Maximum = Math.Min(table.Rows.Count, _param.MaxRows);
                }

                //写入数据
                for (int iRow = 0; iRow < table.Rows.Count && iRow < _param.MaxRows; iRow++)
                {
                    System.Data.DataRow dr = table.Rows[iRow];
                    Row row = null;
                    int rowIndex = _param.StartRow + iRow;
                    if (rowIndex > dataRange.Rows.Count)
                    {
                        //添加新行
                        row = dataRange.Rows.Add(ref missing);
                    }
                    else
                    {
                        row = dataRange.Rows[rowIndex];
                    }
                    for (int col = 0; col < columns.Length; col++)
                    {
                        object v = dr[columns[col]];
                        string value = "";
                        if (v != DBNull.Value)
                        {
                            value = Convert.ToString(v);
                        }
                        if (table.Columns[columns[col]].Caption.Equals(Constant.PhotoTag))
                        {
                            //导出图片
                            string fileName = (string)value;
                            if (System.IO.File.Exists(fileName))
                            {
                                row.Cells[_param.StartColumn + col].Range.InlineShapes.AddPicture(fileName, ref missing, ref missing, ref missing);
                            }
                            else
                            {
                                row.Cells[_param.StartColumn + col].Range.Text = String.Empty;
                            }
                        }
                        else
                        {
                            row.Cells[_param.StartColumn + col].Range.Text = value;
                        }
                    }
                    if (ProgressBar != null)
                    {
                        ProgressBar.Value = iRow + 1;
                    }
                }
                
                ok = true;

            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }

            return ok;
        }

        /// <summary>
        /// 数据卡和数据表混合导出
        /// </summary>
        /// <param name="table"></param>
        /// <param name="docFile"></param>
        /// <returns></returns>
        public bool ExportCombo(System.Data.DataRow dataRow, System.Data.DataTable table)
        {
            bool ok = false;

            object missing = Type.Missing;
            try
            {
                OpenDocument();

                //获取列名称
                string[] columns = GetColumns(table);

                //替换
                object replaceOption = WdReplace.wdReplaceAll;
                for (int i = 0; i < columns.Length;i++)
                {
                    object v = dataRow[columns[i]];
                    object value = "";
                    if (v != DBNull.Value)
                    {
                        value = Convert.ToString(v);
                    }
                    //查找字符串
                    object oldStr = string.Format(_param.ReplaceRule, columns[i].ToUpper());

                    _doc.Content.Find.Text = (string)oldStr;
                    _doc.Content.Find.Execute(ref oldStr, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                       ref value, ref replaceOption, ref missing, ref missing, ref missing, ref missing);
                }

                //获取表格
                Table dataRange = GetDocTable(_doc, _app, columns);

                if (ProgressBar != null)
                {
                    ProgressBar.Value = 0;
                    ProgressBar.Maximum = table.Rows.Count;
                }
                //写入数据
                for (int iRow = 0; iRow < table.Rows.Count; iRow++)
                {
                    System.Data.DataRow dr = table.Rows[iRow];
                    Row row = null;
                    int rowIndex = _param.StartRow + iRow;
                    if (rowIndex > dataRange.Rows.Count)
                    {
                        //添加新行
                        row = dataRange.Rows.Add(ref missing);
                    }
                    else
                    {
                        row = dataRange.Rows[rowIndex];
                    }
                    for (int col = 0; col < columns.Length; col++)
                    {
                        object v = dr[columns[col]];
                        string value = "";
                        if (v != DBNull.Value)
                        {
                            value = Convert.ToString(v);
                        }
                        row.Cells[_param.StartColumn + col].Range.Text = value;
                    }
                    if (ProgressBar != null)
                    {
                        ProgressBar.Value = iRow + 1;
                    }
                }

                ok = true;

            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }

            return ok;
        }

        /// <summary>
        /// 打开模版文档
        /// </summary>
        /// <param name="_app"></param>
        /// <param name="filename"></param>
        /// <returns></returns>
        private void OpenDocument()
        {
            if (_doc == null)
            {
                _app = new Application();
                object missing = Type.Missing;
                if (System.IO.File.Exists(_param.TemplateFile))
                {
                    //复制文件
                    System.IO.File.Copy(_param.TemplateFile, _docFile, true);
                    object filename = _docFile;
                    _doc = _app.Documents.Open(ref filename, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing,
                        ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                    _hasCopied = true;
                }
                else
                {
                    //创建空文档
                    _doc = _app.Documents.Add(ref missing, ref missing, ref missing, ref missing);
                    _hasCopied = false;
                }
            }
        }

        /// <summary>
        /// 获取配置字段
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        private string[] GetColumns(System.Data.DataTable table)
        {
            string[] columns = _param.Columns;
            if (columns == null)
            {
                int index = 0;
                columns = new string[table.Columns.Count];
                foreach (System.Data.DataColumn dc in table.Columns)
                {
                    columns[index] = dc.ColumnName;
                    index++;
                }
            }
            return columns;
        }

        /// <summary>
        /// 根据配置获取Word表格
        /// </summary>
        /// <param name="book"></param>
        /// <returns></returns>
        private Table GetDocTable(Document _doc,Application _app,string[] columns)
        {
            Table table = null;
            object missing = Type.Missing;
            if (_doc.Content.Tables.Count>0)
            {
                if (_param.TableIndex > _doc.Content.Tables.Count )
                {
                    //超出范围，获取第一个
                    table = _doc.Content.Tables[1];
                }
                else
                {
                    table = _doc.Content.Tables[_param.TableIndex];
                }
            }
            else
            {
                object autoFitBehavior = Microsoft.Office.Interop.Word.WdAutoFitBehavior.wdAutoFitWindow;
                table = _doc.Content.Tables.Add(_app.Selection.Range, 2, columns.Length, ref missing, ref autoFitBehavior);
                //在第一行填入列头
                for(int i=0;i<columns.Length;i++)
                {
                    table.Cell(1, i+1).Range.Text = columns[i];
                }
            }
            return table;
        }

        /// <summary>
        /// 向左移动若干字符位置
        /// </summary>
        /// <param name="leftMoveCount">向左移动若干字符个数</param>
        /// <returns>是否成功</returns>
        private void MoveLeftChar(int leftMoveCount)
        {
            object wUnit = (object)WdUnits.wdCharacter;
            object opCount = leftMoveCount;
            object missing = Type.Missing;
            _doc.Application.Selection.MoveLeft(ref wUnit, ref opCount, ref missing);
        }

        /// <summary>
        /// 从当前位置开始删除指定数目的字符
        /// </summary>
        /// <param name="count">要删除的字符数</param>
        /// <returns>是否成功</returns>
        private void DeleteChar(int count)
        {
            object wUnit = (object)WdUnits.wdCharacter;
            object charCount = count;
            _doc.Application.Selection.Delete(ref wUnit, ref charCount);
        }
    }
}
